#include <QDir>
#include <QDebug>
#include <QVBoxLayout>
#include <QGroupBox>
#include <QComboBox>
#include <QGridLayout>
#include <QLabel>

#include "iqtprojectgenerator.h"

IQtProjectGenerator::IQtProjectGenerator(QObject * parent)
    : QObject(parent), m_selectionDone(false)
{
    // Read available plugin information
    QDir pluginDirectory(QDir::currentPath() + PLUGINS_DIR);
    foreach (QString plugin, pluginDirectory.entryList(QDir::Dirs | QDir::NoDotAndDotDot))
    {
        QFile pluginXml(pluginDirectory.canonicalPath() + "/" + plugin + "/" + plugin + ".xml");
        if (pluginXml.exists() && pluginXml.open(QFile::ReadOnly))
        {
            HybridPluginXmlHandler handler(&pluginXml);
            QSharedPointer<HybridPlugin> plugin = handler.parse();
            m_plugins.append(plugin);
            qDebug() << "Found plugin:" << m_plugins.last()->name();
        }
    }
}

IQtProjectGenerator::~IQtProjectGenerator()
{
    ;
}

void IQtProjectGenerator::confirmPluginPlatform()
{
    foreach (QSharedPointer<HybridPlugin> plugin, m_plugins)
    {
        plugin->conformingVersion(platform());
    }
    m_selectionDone = true;
}

const QList< QSharedPointer<HybridPlugin> >& IQtProjectGenerator::plugins()
{
    if (!m_selectionDone)
        confirmPluginPlatform();

    return m_plugins;
}

QWidget * IQtProjectGenerator::createSettingsPluginsWidget(QWidget * parent)
{
    qDebug() << "Create plugins widget";

    QWidget *widget = new QWidget(parent);
    QVBoxLayout *layout = new QVBoxLayout();
    layout->setContentsMargins(0, 0, 0, 0);

    QGroupBox *group = new QGroupBox(widget);
    group->setTitle("Plugin Settings");
    layout->addWidget(group);

    QGridLayout *grid = new QGridLayout(widget);
    group->setLayout(grid);

    int rows = 0; // Counter for rows in the grid layout
    int item = 1; // Counter for platforms
    foreach (QSharedPointer<HybridPlugin> plugin, plugins())
    {
        QLabel *label = new QLabel(widget);
        label->setText("Plugin \"" + plugin->name() + "\"");
        grid->addWidget(label, rows, 0);

        QComboBox *combo = new QComboBox(widget);
        // An empty selection, identify by plugin name and zero index
        combo->addItem("Do not include any version in the project", plugin->name() + "_0");
        foreach (QSharedPointer<HybridPluginPlatform> platform, plugin->platforms())
        {
            QString format = platform->format() == HybridPluginPlatform::Source ? "Source" : "Library";
            QString config = platform->configuration() == HybridPluginPlatform::Release ? "Release" : "Debug";
            QString identification = plugin->name() + "_" + QString::number(item); // Identification for lookup
            m_selection.insert(identification, platform); // Add the item to map to enable selection lookup
            combo->addItem(format + ": " +
                           platform->name() + " " +
                           QString::number(platform->version()) +
                           " (Qt " + QString::number(platform->qtVersion()) + ", " + config + ")",
                           identification);

            if (platform == plugin->selectedPlatform())
            {
                // Set the current item active
                combo->setCurrentIndex(combo->count() - 1);
            }
            item++;
        }
        grid->addWidget(combo, rows, 1);
        rows++;
    }

    QLabel *note = new QLabel(widget);
    note->setText("Note: A compatible version is selected by default. Using a non-compatible version may cause the project not to compile. These settings are not persisted across sessions.");
    note->setWordWrap(true);
    grid->addWidget(note, rows, 1);
    grid->setColumnStretch(1, 1);

    layout->addStretch(1);
    widget->setLayout(layout);
    return widget;
}

void IQtProjectGenerator::savePluginSettings(QWidget *settingsWidget)
{
    // Check that the plugin widget is prepared, and extract the current selection
    // from it. The layout *must* be exactly as in the widget creation function above,
    // or we are going to have problems.
    if (settingsWidget)
    {
        QGridLayout *grid = qobject_cast<QGridLayout *>(settingsWidget->layout()->itemAt(0)->widget()->layout());
        if (grid)
        {
            for (int row = 0; row < grid->rowCount(); row++)
            {
                QComboBox *combo = qobject_cast<QComboBox *>(grid->itemAtPosition(row, 1)->widget());
                if (combo)
                {
                    QRegExp rx("^(.+)_([0-9]+)$");
                    QString identification = combo->itemData(combo->currentIndex()).toString();
                    if (rx.indexIn(identification) != -1)
                    {
                        QString pluginName = rx.cap(1);
                        qDebug() << "Checking settings for" << pluginName;
                        bool ok;
                        int index = rx.cap(2).toInt(&ok);
                        if (ok && index > 0)
                        {
                            QSharedPointer<HybridPluginPlatform> platform = m_selection.value(identification);
                            platform->plugin().selectPlatform(platform);
                            qDebug() << "Selected platform" << platform->name() << platform->version();
                        }
                        else
                        {
                            // Clear selection. First we have to find the plugin by its name
                            qDebug() << "Clearing platform selection for plugin" << pluginName;
                            foreach (QSharedPointer<HybridPlugin> plugin, m_plugins)
                            {
                                if (plugin->name() == pluginName)
                                {
                                    plugin->selectPlatform(QSharedPointer<HybridPluginPlatform>(0));
                                    qDebug() << "Cleared platform selection";
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    // Plugin selection is done here at the latest
    m_selectionDone = true;
}
